package es;

import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequestBuilder;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetItemResponse;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.*;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.DeleteByQueryAction;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.script.mustache.SearchTemplateRequestBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.filters.Filters;
import org.elasticsearch.search.aggregations.bucket.filters.FiltersAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.filters.FiltersAggregator;
import org.elasticsearch.search.aggregations.metrics.avg.Avg;
import org.elasticsearch.search.aggregations.metrics.cardinality.Cardinality;
import org.elasticsearch.search.aggregations.metrics.max.Max;
import org.elasticsearch.search.aggregations.metrics.min.Min;
import org.elasticsearch.search.aggregations.metrics.sum.Sum;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.junit.Test;

import java.net.InetAddress;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class ESJunit {
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

    /**
     * get查询数据
     *
     * @throws Exception
     */
    @Test
    public void getES() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "callcenter-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        //数据查询
        GetResponse response = client.prepareGet("lib1", "user", "2gbiHGoBLlaVo-iAEFan").execute().actionGet();
        Map<String, Object> sourceMap = response.getSource();
        sourceMap.forEach((key, value) -> {
            if ("birthday".equals(key)) {
                try {
                    Date parse = sdf.parse(String.valueOf(value));
                    System.out.println("时间: " + sdf.format(parse));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(key + " " + value + "  " + value.getClass());
        });

        client.close();
    }

    /**
     * put添加文档
     */
    @Test
    public void putEs() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "callcenter-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        //文档类容创建
        XContentBuilder contentBuilder = XContentFactory.jsonBuilder().startObject()
                .field("name", "小明")
                .field("address", "杭州").field("age", 30)
                .field("interests", "登山骑行唱歌").field("birthday", new Date()).endObject();

        //添加文档操作
        IndexResponse response = client.prepareIndex("lib1", "user", "6").setSource(contentBuilder).get();
        System.out.println("状态: " + response.status().name() + " " + response.status().getStatus());
        System.out.println(response.toString());

        client.close();
    }

    /**
     * 删除操作
     */
    @Test
    public void deleteEs() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "my-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        //删除文档
        DeleteResponse response = client.prepareDelete("lib1", "user", "10").get();
        System.out.println("状态: " + response.status().name() + " " + response.status().getStatus());
        System.out.println(response.toString());
        //断开连接
        client.close();
    }

    /**
     * update 操作
     */
    @Test
    public void updateEs() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "my-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        //update更新内容:(doc中也可以使用XContentBuilder)
        UpdateRequest request = new UpdateRequest("lib1", "user", "100");
        Map<String, Object> sourceMap = new HashMap<>();
        sourceMap.put("birthday", "2019-02-26");
        sourceMap.put("age", 40);
        request.doc(sourceMap);
        //执行更新
        //UpdateResponse updateResponse = client.prepareUpdate("lib1", "user", "100").setDoc(sourceMap).get();
        UpdateResponse response = client.update(request).get();
        System.out.println("状态: " + response.status().name() + " " + response.status().getStatus());

        //关闭连接
        client.close();
    }

    /**
     * upsert更新文档
     */
    @Test
    public void upsertEs() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "my-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        //upsert操作文档内容(可以使用map封装内容)
        XContentBuilder contentBuilder = XContentFactory.jsonBuilder().startObject()
                .field("name", "赵龙")
                .field("address", "北京").field("age", 30)
                .field("interests", "习武锻炼身体").field("birthday", new Date()).endObject();

        //update操作文档内容
        UpdateRequest updateRequest = new UpdateRequest("lib1", "user", "10");
        Map<String, Object> sourceMap = new HashMap<>();
        sourceMap.put("birthday", "2019-05-26");
        sourceMap.put("age", 40);
        updateRequest.doc(sourceMap).upsert(contentBuilder);

        //执行操作
        UpdateResponse response = client.update(updateRequest).get();
        System.out.println("状态: " + response.status().name() + " " + response.status().getStatus());

        //断开连接
        client.close();
    }

    /**
     * mget批量查询操作
     */
    @Test
    public void mgetEs() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "my-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        MultiGetResponse multiResponses = client.prepareMultiGet().add("lib1", "user", "1", "2")
                .add("lib3", "user", "1").get();
        for (MultiGetItemResponse item : multiResponses) {
            GetResponse gr = item.getResponse();
            if (gr != null && gr.isExists()) {
                System.out.println(gr.getSourceAsString());
            }
        }

        //断开连接
        client.close();
    }

    /**
     * bulk实现批量添加操作
     */
    @Test
    public void bulkBatch() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "my-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
/*        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        BulkRequestBuilder builder = client.prepareBulk();
        //新增
        Map<String, Object> insertMap = new HashMap<>();
        insertMap.put("name", "诸葛亮");
        insertMap.put("age", 20);
        insertMap.put("address", "上海");
        insertMap.put("interests", "策划");
        insertMap.put("birthday", "2010-10-09");
        IndexRequestBuilder indexRequest = client.prepareIndex("lib1", "user", "3").setSource(insertMap);

        //更新u
        UpdateRequest updateRequest = new UpdateRequest("lib1", "user", "1");
        Map<String, Object> sourceMap = new HashMap<>();
        sourceMap.put("name", "小明同学");
        sourceMap.put("age", 19);
        updateRequest.doc(sourceMap);

        //删除
        DeleteRequestBuilder deleteBuilder = client.prepareDelete("lib1", "user", "10");

        //批量执行操作
        BulkResponse bulkItemResponses = builder.add(indexRequest).add(updateRequest).add(deleteBuilder).get();
        System.out.println("状态: " + bulkItemResponses.status().name() + " " + bulkItemResponses.status().getStatus());
        if (bulkItemResponses.hasFailures()) {
            System.out.println("失败了!!");
        }

        //断开连接
        client.close();
    }

    /**
     * match_all查询
     */
    @Test
    public void matchAllEs() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "my-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("192.168.33.2"), 9300));

        //MatchAll
        MatchAllQueryBuilder qb = QueryBuilders.matchAllQuery();
        SearchResponse sr = client.prepareSearch("lib3")
                .setTypes("user").setQuery(qb)
                .setSize(3).get();
        SearchHits hits = sr.getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }

        //断开连接
        client.close();
    }

    /**
     * match query查询所有操作
     */
    @Test
    public void matchQueryEs() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "my-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
       /* TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("192.168.33.2"), 9300));

        //创建queryBuilder: 查询interests里包含 "登山" 或 "唱歌"(match查询时,ES会对interests进行分词)
        MatchQueryBuilder qb = QueryBuilders.matchQuery("interests", "登山唱歌");
        SearchResponse sr = client.prepareSearch("lib1").setTypes("user").setQuery(qb)
                .setPostFilter(QueryBuilders.rangeQuery("age").gt(20)).setSize(3).get();
        SearchHits hits = sr.getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }

        //断开连接
        client.close();
    }

    /**
     * multi match query查询所有操作
     */
    @Test
    public void multiMatchQueryEs() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "my-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));


        //创建queryBuilder: 查询interests, name里包含"登山"的数据
        MultiMatchQueryBuilder qb = QueryBuilders.multiMatchQuery("登山", "interests", "name");
        SearchResponse sr = client.prepareSearch("lib1").setTypes("user").setQuery(qb).setSize(3).get();
        SearchHits hits = sr.getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }

        //断开连接
        client.close();
    }

    /**
     * 查询删除操作
     *
     * @throws Exception
     */
    @Test
    public void matchQueryAndDeleteEs() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "my-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        //创建查询删除操作
        BulkByScrollResponse response = DeleteByQueryAction.INSTANCE.newRequestBuilder(client)
                .filter(QueryBuilders.matchQuery("name", "小明"))
                .source("lib1").get();

        System.out.println("状态: " + response.getStatus());
        System.out.println("删除文档个数: " + response.getDeleted());
        //断开连接
        client.close();
    }

    /**
     * term查询(ES不会对查询条件进行分词。这种查询适合keyword 、numeric、date)
     *
     * @throws Exception
     */
    @Test
    public void termQueryEs() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "callcenter-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        //创建term查询
        QueryBuilder termBuilder = QueryBuilders.termQuery("interests", "登山");
        SearchResponse response = client.prepareSearch("lib1").setTypes("user")
                .setQuery(termBuilder).addSort("age", SortOrder.DESC).setFrom(2).setSize(2).get();
        System.out.println("状态: " + response.status());
        System.out.println("总数: " + response.getHits().totalHits);
        SearchHits hits = response.getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }

        //断开连接
        client.close();
    }

    /**
     * term查询(ES不会对查询条件进行分词。这种查询适合keyword 、numeric、date)
     *
     * @throws Exception
     */
    @Test
    public void termsQueryEs() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "my-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        //创建term查询
        QueryBuilder termBuilder = QueryBuilders.termsQuery("interests", "策划", "骑行");
        SearchResponse response = client.prepareSearch("lib1").setQuery(termBuilder).setSize(3).get();
        SearchHits hits = response.getHits();
        System.out.println("状态: " + response.status());
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }

        //断开连接
        client.close();
    }

    /**
     * 使用范围range,前缀prefix, 通配符wildcard, 模糊查询fuzzy, type查询, ID查询
     *
     * @throws Exception
     */
    @Test
    public void otherQueryEs() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "my-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        //range查询
        //QueryBuilder termBuilder = QueryBuilders.rangeQuery("birthday").from("2010-01-01").to("2010-12-30");

        //前缀查询
        //QueryBuilder termBuilder = QueryBuilders.prefixQuery("name", "小");

        //通配符查询
        //QueryBuilder termBuilder = QueryBuilders.wildcardQuery("interests", "*骑*");

        //正则匹配查询
        //QueryBuilder termBuilder = QueryBuilders.regexpQuery("interests", "[山]?");

        //模糊查询:fuzzy
        //QueryBuilder termBuilder = QueryBuilders.fuzzyQuery("name", "youyon");

        //指定type查询
        //QueryBuilder termBuilder = QueryBuilders.typeQuery("user");

        //指定ID查询
        QueryBuilder termBuilder = QueryBuilders.idsQuery("user").addIds("1", "2", "3");

        SearchResponse response = client.prepareSearch("lib1").setQuery(termBuilder).get();
        SearchHits hits = response.getHits();
        System.out.println("状态: " + response.status());
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }

        //断开连接
        client.close();
    }

    /**
     * 聚合查询
     *
     * @throws Exception
     */
    @Test
    public void aggregationQueryEs() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "my-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));
        //最大值
        AggregationBuilder agg = AggregationBuilders.max("aggMax").field("age");
        SearchResponse response1 = client.prepareSearch("lib1").addAggregation(agg).get();
        Max max = response1.getAggregations().get("aggMax");
        System.out.println("最大值: " + max.getValue());

        //最小值
        AggregationBuilder aggMin = AggregationBuilders.min("aggMin").field("age");
        SearchResponse response2 = client.prepareSearch("lib1").addAggregation(aggMin).get();
        Min min = response2.getAggregations().get("aggMin");
        System.out.println("最小值: " + min.getValue());

        //平均数
        AggregationBuilder aggAvg = AggregationBuilders.avg("aggAvg").field("age");
        SearchResponse response3 = client.prepareSearch("lib1").addAggregation(aggAvg).get();
        Avg avg = response3.getAggregations().get("aggAvg");
        System.out.println("平均值: " + avg.getValue());

        //求和
        AggregationBuilder aggSum = AggregationBuilders.sum("aggSum").field("age");
        SearchResponse response4 = client.prepareSearch("lib1").addAggregation(aggSum).get();
        Sum sum = response4.getAggregations().get("aggSum");
        System.out.println("平均值: " + sum.getValue());

        //求基数
        AggregationBuilder aggCardinality = AggregationBuilders.cardinality("aggCardinality").field("age");
        SearchResponse response5 = client.prepareSearch("lib1").addAggregation(aggCardinality).get();
        Cardinality card = response5.getAggregations().get("aggCardinality");
        System.out.println("基数: " + card.getValue());

        //断开连接
        client.close();
    }

    /**
     * Query String查询
     *
     * @throws Exception
     */
    @Test
    public void queryStringEs() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "my-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        //指定属性查询
        //QueryBuilder builder = QueryBuilders.commonTermsQuery("interests", "骑行");

        //不指定属性:全文搜索(每个字段都会进行匹配)
        //QueryBuilder builder = QueryBuilders.queryStringQuery("登山");

        //"+"必须包含, "-"不包含 (simpleQueryStringQuery只要满足一个条件就能匹配)
        QueryBuilder builder = QueryBuilders.simpleQueryStringQuery("+登山 -策划");

        SearchResponse response = client.prepareSearch("lib1").setQuery(builder).get();
        SearchHits hits = response.getHits();
        System.out.println("状态: " + response.status());
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }

        //断开连接
        client.close();
    }

    /**
     * 组合查询
     *
     * @throws Exception
     */
    @Test
    public void boolQueryEs() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "my-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        //constantScore查询:不计算相关度分数查询
        //ConstantScoreQueryBuilder builder = QueryBuilders.constantScoreQuery(QueryBuilders.wildcardQuery("name", "小*"));


        //bool组合查询: name包含"小"开头,interests不包含"游泳",address可以是"上海", birthday大于等于1991-01-01
        BoolQueryBuilder builder = QueryBuilders.boolQuery().must(QueryBuilders.wildcardQuery("name", "小*"))
                .mustNot(QueryBuilders.matchQuery("interests", "游泳"))
                .should(QueryBuilders.matchQuery("address", "上海"))
                .filter(QueryBuilders.rangeQuery("birthday").gte("1991-01-01").format("yyyy-MM-dd"));
        SearchResponse response = client.prepareSearch("lib1").setQuery(builder).get();
        SearchHits hits = response.getHits();
        System.out.println("状态: " + response.status());
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }

        //断开连接
        client.close();
    }

    /**
     * 聚合查询
     *
     * @throws Exception
     */
    @Test
    public void groupQueryEs() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "my-application").build();

        //创建访问es服务器的客服端: 指定settings 和 集群节点
        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.33.2"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        //按age进行group by
        //TermsAggregationBuilder builder = AggregationBuilders.terms("terms").field("age");

        //统计name包含"小"的数据
  /*      WildcardQueryBuilder builder = QueryBuilders.wildcardQuery("name", "*小*");
        FilterAggregationBuilder aggregation = AggregationBuilders.filter("filter", builder);
        SearchResponse response = client.prepareSearch("lib1").addAggregation(aggregation).execute().get();
        System.out.println("状态: " + response.status());
        Filter filter = response.getAggregations().get("filter");
        System.out.println(filter.getDocCount());*/

        //统计: 生日大于1991 和 name包含"小"字的数据
        FiltersAggregationBuilder aggregation = AggregationBuilders.filters("filters",
                new FiltersAggregator.KeyedFilter("生日大于1991",
                QueryBuilders.rangeQuery("birthday").gte("1991-01-01")),
                new FiltersAggregator.KeyedFilter("name包含小字", QueryBuilders.wildcardQuery("name", "*小*")));
        SearchResponse response = client.prepareSearch("lib1").addAggregation(aggregation).execute().get();
        System.out.println(response.getAggregations().get("filters").toString());
        Filters filters = response.getAggregations().get("filters");
        for (Filters.Bucket bucket : filters.getBuckets()){
            System.out.println(bucket.getKey() + ": " + bucket.getDocCount());
        }

        //range聚合操作
/*        RangeAggregationBuilder rangeAggregation = AggregationBuilders.range("range").field("age")
                .addUnboundedTo(20) //(, to) 小于20的数据
                .addRange(20, 30)   //[from, to)  [20, 30)之间数据
                .addUnboundedFrom(30);//[from, ) 大于等于30的数据

        SearchResponse response = client.prepareSearch("lib1").addAggregation(rangeAggregation).execute().actionGet();
        System.out.println("状态: " + response.status().name() + " " + response.status().getStatus());
        Range range = response.getAggregations().get("range");
        for(Range.Bucket bucket : range.getBuckets()){
            System.out.println(bucket.getKey() + ": " + bucket.getDocCount());
        }*/

        //missing聚合: 统计字段为null的数据
/*        MissingAggregationBuilder aggregation = AggregationBuilders.missing("missing").field("birthday");
        SearchResponse response = client.prepareSearch("lib1").addAggregation(aggregation).execute().actionGet();
        System.out.println("状态: " + response.status().name() + " " + response.status().getStatus());
        Missing missing = response.getAggregations().get("missing");
        System.out.println(missing.getType() + " " + missing.getName() + " " + missing.getDocCount());*/

        //断开连接
        client.close();
    }

    /**
     * 获取集群信息
     */
    @Test
    public void clusterMasg() throws Exception {
        //指定ES集群名称
        Settings settings = Settings.builder().put("cluster.name", "application").build();

        //ES高版本6.5.4
        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("172.16.85.215"), 9300));*/
        //创建访问es服务器的客服端: 指定settings 和 集群节点
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        ClusterHealthResponse health = client.admin().cluster().prepareHealth().get();
        System.out.printf("集群名称: %s", health.getClusterName());
        System.out.println();
        System.out.printf("节点总数: %s", health.getNumberOfDataNodes());
        System.out.println();
        health.getIndices().forEach((key, value) -> {
            System.out.printf("节点信息: key = %s, value = %s", key, value);
        });
        //断开连接
        client.close();
    }

    /**
     * scroll滚动查询数据
     * @throws Exception
     */
    @Test
    public void scrollQueryEs() throws Exception{
        Settings settings = Settings.builder().put("cluster.name", "application")
                .put("client.transport.sniff", true).build();

        //ES高版本6.5.4
        /*TransportClient client = new PreBuiltTransportClient(settings).addTransportAddresses(new TransportAddress(InetAddress.getByName("172.16.85.215"),
                9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        SearchResponse response = client.prepareSearch("lib1").setTypes("user")
                .setQuery(QueryBuilders.rangeQuery("age")).addSort("age", SortOrder.DESC)
                .setScroll(new TimeValue(30000))
                .setSize(1)
                .get();

        long branchCount = 1;
        do {
            System.out.println("查询批次: " + branchCount++  + " 总数: " + response.getHits().totalHits);
            for (SearchHit hit : response.getHits()) {
                System.out.println(hit.getSourceAsString());
            }
            //每次查询的时候都需要设置过期时间
            response = client.prepareSearchScroll(response.getScrollId()).setScroll(new TimeValue(30000)).execute().actionGet();
        }while (response.getHits().getHits().length != 0);
    }

    /**
     * search_after查询
     * @throws Exception
     */
    @Test
    public void searchAfterQuery() throws Exception {
        Settings settings = Settings.builder().put("cluster.name", "comment").put("client.transport.sniff", true).build();
        TransportClient client = new PreBuiltTransportClient(settings).addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("10.2.98.164"), 9300));
        SearchRequestBuilder builder = client.prepareSearch("user_index").setTypes("user").setSize(2).addSort("age", SortOrder.ASC).addSort("id", SortOrder.ASC);

        Object[] searchAfter = new Object[]{0, 0};
        SearchResponse response = builder.setQuery(QueryBuilders.matchAllQuery()).get();
        while (response.getHits().getHits().length > 0) {
            SearchHit[] hits = response.getHits().getHits();
            for (SearchHit hit : hits) {
                System.out.println(hit.getSourceAsString());
            }
            Map<String, Object> lastMap = hits[hits.length - 1].getSource();
            searchAfter[0] = lastMap.get("age");
            searchAfter[1] = lastMap.get("id");
            System.out.println("search_after查询条件:" + Arrays.asList(searchAfter));
            response = builder.searchAfter(searchAfter).get();
        }
        System.out.println("查询数据结束....................");
        //关闭连接
        client.close();
    }

    /**
     * 分页查询
     */
    @Test
    public void pageQueryEs() throws Exception {
        Settings settings = Settings.builder().put("cluster.name", "callcenter-application")
                .put("client.transport.sniff", true).build();

        /*TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("172.16.85.215"), 9300));*/
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        RangeQueryBuilder builder = QueryBuilders.rangeQuery("age").from(20).to(30);
        SearchResponse response = client.prepareSearch("lib1").setTypes("user")
                .setQuery(builder)
                .addSort("age", SortOrder.DESC)
                .setFrom(0).setSize(2).get();

        System.out.println(response);
        System.out.println("====================================");
        System.out.println("总数: " + response.getHits().totalHits);
        for (SearchHit hit : response.getHits().getHits()) {
            System.out.println(hit.getSourceAsString());
        }

        //关闭连接
        client.close();
    }

    /**
     * 脚本模本查询
     */
    @Test
    public void scriptQueryEs() throws Exception {
        Settings settings = Settings.builder().put("cluster.name", "application")
                .put("client.transport.sniff", true).build();

        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("172.16.85.215"), 9300));

        Map<String, Object> template_params = new HashMap<>();


        SearchResponse response = new SearchTemplateRequestBuilder(client)
                .setScript("page_query_by_brand")
                .setScriptType(ScriptType.FILE)
                .setScriptParams(template_params)
                .setRequest(new SearchRequest())
                .get()
                .getResponse();

        client.close();
    }
}
